package com.leonyr.smartipaddemo.crop;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbDevice;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.leonyr.mvvm.util.RxSchedulers;
import com.leonyr.smartipaddemo.R;
import com.leonyr.smartipaddemo.conn.FileName;
import com.leonyr.smartipaddemo.view.CircleSeekBar;
import com.serenegiant.helper.BitmapHelper;
import com.serenegiant.helper.UvcCameraHelper;
import com.serenegiant.usb.DeviceFilter;
import com.serenegiant.usb.USBMonitor;
import com.serenegiant.usb.UVCCamera;
import com.serenegiant.usbcameracommon.AbstractUVCCameraHandler;
import com.serenegiant.widget.CameraViewInterface;
import com.serenegiant.widget.UVCCameraTextureView;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;

import io.reactivex.Observable;
import io.reactivex.functions.Consumer;

public class MineCameraActivity extends AppCompatActivity implements View.OnClickListener,
        MoreSetFragment.OnSeekBarProgressChangedListener,
        ConShutterFragment.OnConSetListener, TextWatcher {
    private static final String TAG = "MineCameraActivity";
    public static final String OUTPUT = "Camera_output";
    public static final String CAMERA_TYPE = "camera_type";
    public static final int TYPE_PHOTO = 0x88;
    //    private final String mFaceModelDir = Environment.getExternalStorageDirectory().getAbsolutePath() +"/pic/";
    private String mFaceModelDir;
    private EditText etAngle;
    private Button btnRotateH;
    private Button btnRotateV;
    private TextView tvResolutionRatio;
    private TextView tvConShutter;
    private TextView tvMoreSet;
    private CircleSeekBar circleSeekBar;
    private TextView tvAnglePersent;
    private ImageButton ibtnTakePhoto;
    private ImageView photoPrew;
    private Button chooseDevice;
    private CameraViewInterface cameraViewInterface;
    private UvcCameraHelper mHelper;


    private int openCameraPid = 48342;
    private int blackPid = 48343;
    private int leftMirror = 1;
    private int upMirror = 1;
    //    private List<Size> sizeiList;
    private List<String> sizesList;
//    private List<Bitmap> photoBit;
    private List<String> photoPathList;
    private Handler handler = new Handler();
    private boolean ifConShut = false;
    private int sheet = 1;//记录连拍的张数

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mine_camera);
        mFaceModelDir = getExternalFilesDir("cache").getAbsolutePath();
        initView();
        initCameraHelper();
    }

    private void setDevice() {
        USBMonitor mUsbMonitor = mHelper.getUsbMonitor();
        final List<DeviceFilter> filter = DeviceFilter.getDeviceFilters(this);
        List<UsbDevice> devices = mUsbMonitor.getDeviceList(filter.get(0));
        if (devices != null && devices.size() > 0) {
            UsbDevice device = devices.get(0);
            mUsbMonitor.requestPermission(device);
        }
    }

    private void initCameraHelper() {
        cameraViewInterface = findViewById(R.id.texture);
        cameraViewInterface.setCallback(new CameraViewInterface.Callback() {
            @Override
            public void onSurfaceCreated(CameraViewInterface cameraViewInterface, Surface surface) {
                boolean res = mHelper.getUsbMonitor().isRegistered();
                if (res) {
                    setDevice();
//                    photoBit = new ArrayList<>();
                    photoPathList = new ArrayList<>();
                }
            }

            @Override
            public void onSurfaceChanged(CameraViewInterface cameraViewInterface, Surface surface, int i, int i1) {

            }

            @Override
            public void onSurfaceDestroy(CameraViewInterface cameraViewInterface, Surface surface) {

            }
        });
        mHelper = UvcCameraHelper.getInstance(new WeakReference<Activity>(this), new WeakReference<Context>(this),
                cameraViewInterface, 1, UVCCamera.FRAME_FORMAT_MJPEG);
        mHelper.setConnectedListener(new UvcCameraHelper.onDeviceConnectedListener() {
            @Override
            public void onConnected(final boolean isOpen) {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (isOpen) {
                            sizesList = mHelper.getSupportPreviewSizesStr();
                            if(sizesList!=null){
                                String[] datas = sizesList.get(0).split("x");
                                if (datas.length == 2) {
                                    Log.d(TAG, "onItemClick: width" + datas[0] + "x" + datas[1]);
                                    mHelper.updateResolution(Integer.parseInt(datas[0]),Integer.parseInt(datas[1]));
                                }
                            }
                            showToast("设备认证成功");
                        } else {
                            showToast("设备认证失败");
                        }
                    }
                });

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
                            mHelper.resetCameraModeValue(UVCCamera.PU_BRIGHTNESS);
                            mHelper.resetCameraModeValue(UVCCamera.PU_CONTRAST);
                            mHelper.resetCameraModeValue(UVCCamera.PU_GAMMA);
                            mHelper.resetCameraModeValue(UVCCamera.PU_WB_TEMP);
                            mHelper.resetCameraModeValue(UVCCamera.PU_SATURATION);
                            mHelper.resetCameraModeValue(UVCCamera.PU_HUE);
                            mHelper.resetCameraModeValue(UVCCamera.PU_SHARPNESS);
                            mHelper.resetCameraModeValue(UVCCamera.PU_BACKLIGHT);
                        }
                    }
                }).start();
            }


            @Override
            public void onAttached(UsbDevice usbDevice) {
                if (usbDevice.getProductId() == openCameraPid) {
                    mHelper.openCamera(openCameraPid);
                }
            }
        });
        mHelper.initUvcCamera( 4000,3000);

        mHelper.getUvcCameraHandler().addCallback(new AbstractUVCCameraHandler.CameraCallback() {
            @Override
            public void onOpen() {
                Log.i("open", TAG);
            }

            @Override
            public void onClose() {
                Log.i("close", TAG);
            }

            @Override
            public void onStartPreview() {
                Log.i("startPreview", TAG);
            }

            @Override
            public void onStopPreview() {
                Log.i("stopPreview", TAG);
            }

            @Override
            public void onStartRecording() {
                Log.i("startRecord", TAG);
            }

            @Override
            public void onStopRecording() {
                Log.i("open", TAG);
            }

            @Override
            public void onError(Exception e) {
                Log.i("error", TAG);
            }

            @Override
            public void onPreview(byte[] data) {
                Log.i("preview", TAG);
            }

            @Override
            public void onPictureTaken(Bitmap bitmap) {
//                if(bitmap!=null){
//                    //添加保存本地，并获取其路径
//                    if(bitmap!=null){
//                        //拍完照，则直接自动识别
//                        Bitmap bitm = BitmapHelper.autoCutBitmap(bitmap);
//                        photoBit.add(bitm);
//                        if(photoBit.size()==sheet){//判断是否拍完
//                            //跳转预览裁剪界面
//                            go2Crop();
//                        }
//                    }
//                }
            }
        });

    }

    private void initView() {
        etAngle = findViewById(R.id.et_angle);
        etAngle.addTextChangedListener(this);
        btnRotateH = findViewById(R.id.horizontal_rotate);
        btnRotateH.setOnClickListener(this);
        btnRotateV = findViewById(R.id.vertical_rotate);
        btnRotateV.setOnClickListener(this);
        tvResolutionRatio = findViewById(R.id.resolution_ratio);
        tvResolutionRatio.setOnClickListener(this);
        tvConShutter = findViewById(R.id.con_shutter);
        tvConShutter.setOnClickListener(this);
        tvMoreSet = findViewById(R.id.more_set);
        tvMoreSet.setOnClickListener(this);
        ibtnTakePhoto = findViewById(R.id.take_photo);
        ibtnTakePhoto.setOnClickListener(this);
        photoPrew = findViewById(R.id.photo_prew);
        photoPrew.setOnClickListener(this);
        chooseDevice = findViewById(R.id.choose_device);
        chooseDevice.setOnClickListener(this);
        tvAnglePersent = findViewById(R.id.tv_anglepersent);
        circleSeekBar = findViewById(R.id.circle_seekbar);
        circleSeekBar.setMaxProgress(360);
        circleSeekBar.setSeekBarChangeListener(new CircleSeekBar.OnSeekChangeListener() {
            @Override
            public void onProgressChange(CircleSeekBar view, int newProgress) {
                tvAnglePersent.setText(Integer.toString(view.getProgress()));
                String text = etAngle.getText().toString().trim();
                if (!TextUtils.isEmpty(text) && TextUtils.equals(text, String.valueOf(newProgress))) {//如果编辑框与轮盘数值相等，则不变
                    ;
                } else {
                    etAngle.setText(String.valueOf(newProgress));
                    mHelper.setRotate(newProgress);
                }
            }
        });

    }

    @Override
    protected void onStart() {
        super.onStart();
        mHelper.workOnStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mHelper != null && !mHelper.getUvcCameraHandler().isOpened()) {
            Log.d(TAG, "onResume: camera");
            mHelper.getUsbMonitor().register();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        mHelper.workOnStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHelper.workOnDestroy();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.horizontal_rotate:
                leftMirror = 0 - leftMirror;
                ((UVCCameraTextureView) cameraViewInterface).letfRightMirror(leftMirror);
                break;
            case R.id.vertical_rotate:
                upMirror = 0 - upMirror;
                ((UVCCameraTextureView) cameraViewInterface).upDownMirror(upMirror);
                break;
            case R.id.resolution_ratio:
                sizesList = mHelper.getSupportPreviewSizesStr();
                AlertDialog.Builder builder = new AlertDialog.Builder(MineCameraActivity.this);
                builder.setTitle("选择分辨率");
                builder.setItems(sizesList.toArray(new String[sizesList.size()]), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
//                        if(sizeiList!=null&&sizeiList.size()>0){
                        String str = sizesList.get(i);
                        String[] datas = str.split("x");
                        if (datas.length == 2) {
                            Log.d(TAG, "onItemClick: width" + datas[0] + "x" + datas[1]);
                            mHelper.updateResolution(Integer.parseInt(datas[0]), Integer.parseInt(datas[1]));
                        }
                        dialogInterface.dismiss();
                    }
                });
                builder.setCancelable(true);
                builder.create();
                builder.show();
                break;
            case R.id.con_shutter:
                ConShutterFragment conShutterFragment = new ConShutterFragment();
                conShutterFragment.show(getSupportFragmentManager(), null);
                break;
            case R.id.more_set:
                int brightness = mHelper.getCameraModeValue(UVCCamera.PU_BRIGHTNESS);
                int contrast = mHelper.getCameraModeValue(UVCCamera.PU_CONTRAST);
                int gama = mHelper.getCameraModeValue(UVCCamera.PU_GAMMA);
                int wbTemp = mHelper.getCameraModeValue(UVCCamera.PU_WB_TEMP);
                int saturation = mHelper.getCameraModeValue(UVCCamera.PU_SATURATION);
                int hue = mHelper.getCameraModeValue(UVCCamera.PU_HUE);
                int sharpness = mHelper.getCameraModeValue(UVCCamera.PU_SHARPNESS);
                int backlight = mHelper.getCameraModeValue(UVCCamera.PU_BACKLIGHT);

                MoreSetFragment moreSetFragment = MoreSetFragment.newInstance(brightness, contrast, gama, wbTemp,
                        saturation, hue, sharpness, backlight);
                getSupportFragmentManager().beginTransaction().replace(R.id.operate_layout, moreSetFragment).commit();
                break;
            case R.id.take_photo:
                if (!ifConShut) {//没有在连拍
                    sheet = 1;
                    takePhoto();
                }
                break;
            case R.id.photo_prew:
                if (photoPathList != null && photoPathList.size() > 0) {
                    go2Crop();
                }
                break;
            case R.id.choose_device:
                USBMonitor mUsbMonitor = mHelper.getUsbMonitor();
                final List<DeviceFilter> filter = DeviceFilter.getDeviceFilters(this);
                List<UsbDevice> devices = mUsbMonitor.getDeviceList(filter.get(0));
                List<String> items = new ArrayList<>();
                for (int i = 0; i < devices.size(); i++) {
                    String name = String.format("UVC Camera:(%x:%x:%s)", devices.get(i).getVendorId(), devices.get(i).getProductId(), devices.get(i).getDeviceName());
                    items.add(name);
                }
                AlertDialog.Builder builder2 = new AlertDialog.Builder(MineCameraActivity.this);
                builder2.setTitle("选择设备");
                builder2.setItems(items.toArray(new String[items.size()]), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (devices != null && i < devices.size()) {
                            UsbDevice device = devices.get(i);
                            if (!mUsbMonitor.hasPermission(device)) {
                                mUsbMonitor.requestPermission(device);
                            }
                            dialogInterface.dismiss();
                        }
                    }
                });
                builder2.setCancelable(true);
                builder2.create();
                builder2.show();
                break;
        }
    }

    private void saveBitmap2File(Bitmap bitmap){
        if (bitmap != null) {
            String path = FileName.getPhotoJpgName();
            String tempPath = new File(getExternalCacheDir(), path).getPath();
//                FileUtil.moveFile(new File(mCtx.getExternalFilesDir("cache"), name), new File(tempPath));
            saveBmpToFile(bitmap, tempPath, Bitmap.CompressFormat.JPEG);
            photoPathList.add(tempPath);
//                Toast.makeText(this, "第一张照片保存成功", Toast.LENGTH_SHORT).show();
        }
    }

    private void go2Crop() {
//        List<String> photoPathList = new ArrayList<>();
//        for (Bitmap bitmapL : photoBit) {
//            if (bitmapL != null) {
//                String path = FileName.getPhotoJpgName();
//                String tempPath = new File(getExternalCacheDir(), path).getPath();
////                FileUtil.moveFile(new File(mCtx.getExternalFilesDir("cache"), name), new File(tempPath));
//                saveBmpToFile(bitmapL, tempPath, Bitmap.CompressFormat.JPEG);
//                photoPathList.add(tempPath);
//            }
//        }

        Intent intent = new Intent();
        intent.putStringArrayListExtra(OUTPUT, (ArrayList<String>) photoPathList);
        setResult(Activity.RESULT_OK, intent);
        finish();
    }

    private void showToast(String content) {
        Toast.makeText(this, content, Toast.LENGTH_SHORT).show();
    }

//    @Override
//    public void onSizeChanged(int index) {
//        if (sizeiList != null && sizeiList.size() > 0) {
//            mHelper.updateResolution(sizeiList.get(index).width, sizeiList.get(index).height);
//            mHelper.startPreview();
//        }
//    }

    @Override
    public void onBrightnessChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_BRIGHTNESS, value);
        }
    }

    @Override
    public void onContrastChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_CONTRAST, value);
        }
    }

    @Override
    public void onGamaChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_GAMMA, value);
        }
    }

    @Override
    public void onWbTempChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_WB_COMPO, value);
        }
    }

    @Override
    public void onSaturaChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_SATURATION, value);
        }
    }

    @Override
    public void onHueChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_HUE, value);
        }
    }

    @Override
    public void onSharpnessChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_SHARPNESS, value);
        }
    }

    @Override
    public void onBacklightChange(int value) {
        if (mHelper != null && mHelper.getUvcCameraHandler().isOpened()) {
            mHelper.setCameraModeValue(UVCCamera.PU_BACKLIGHT, value);
        }
    }

    @Override
    public void onConSet(final int sheet, long interval) {
        if (sheet > 1) {
            this.sheet = sheet;
            Timer shutTimer = new Timer();
            TimerTask shutTask = new TimerTask() {
                int count = sheet;

                @Override
                public void run() {
                    if (count > 0) {
                        count--;
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                takePhoto();
//                                showToast("拍第" + (count + 1) + "张");
                            }
                        });
                    } else {
                        cancel();
                        shutTimer.cancel();
                        ifConShut = false;
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                //跳转预览界面
                                if (photoPathList.size() > 0) {
                                    go2Crop();
                                }
                            }
                        });
                    }
                }
            };
            CountDownFragment countDownFragment = new CountDownFragment();
            countDownFragment.setOnDismissListener(new DialogInterface.OnDismissListener() {
                @Override
                public void onDismiss(DialogInterface dialogInterface) {
                    ifConShut = true;
//                    showToast("开始拍照");
                    shutTimer.schedule(shutTask, 0, interval);
                }
            });
            countDownFragment.show(getSupportFragmentManager(), null);

        }
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void afterTextChanged(Editable editable) {
        String angleS = editable.toString().trim();
        if (!TextUtils.isEmpty(angleS)) {
            int angle = 0;
            int anglei = Integer.parseInt(angleS);
            if (anglei < 0) {
                angle = 0;
            } else if (anglei > 360) {
                angle = 360;
            } else {
                angle = anglei;
            }
            circleSeekBar.setProgress(angle);
            mHelper.setRotate(angle);
        }
    }

    public static boolean saveBmpToFile(Bitmap bmp, String path, Bitmap.CompressFormat format) {
        if (bmp == null || bmp.isRecycled())
            return false;

        OutputStream stream = null;
        try {
            File file = new File(path);
            File filePath = file.getParentFile();
            if (!filePath.exists()) {
                filePath.mkdirs();
            }
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            }
            stream = new FileOutputStream(path);
            return bmp.compress(format, 100, stream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } finally {
            if (null != stream) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void takePhoto() {
        Observable.fromCallable(new Callable<Bitmap>() {//返回bitmap
            @Override
            public Bitmap call() throws Exception {
                sizesList = mHelper.getSupportPreviewSizesStr();
                if(sizesList!=null){
                    String[] datas = sizesList.get(0).split("x");
                    if (datas.length == 2) {
                        Log.d(TAG, "onItemClick: width" + datas[0] + "x" + datas[1]);
                        mHelper.setPreviewWidth(Integer.parseInt(datas[0]));
                        mHelper.setPreviewHeight(Integer.parseInt(datas[1]));
//                        mHelper.setPreviewWidth(4000);
//                        mHelper.setPreviewHeight(3000);
                    }
                }
                Bitmap bitmap = mHelper.takePhoto();
//                Bitmap bitm = BitmapHelper.autoCutBitmap(bitmap);
//                 Bitmap bitmapC = BitmapHelper.autoCorrectBitmap(bitm);
                saveBitmap2File(bitmap);
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG,40,os);
                ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
                Bitmap compressb = BitmapFactory.decodeStream(is,null,null);
                bitmap.recycle();
                is.close();
                os.close();
                return compressb;
            }
        }).compose(RxSchedulers.IOMain())
                .subscribe(new Consumer<Bitmap>() {

                    @Override
                    public void accept(Bitmap bitmap) throws Exception {
                        if (photoPathList == null) {
                            return;
                        }
//                        photoBit.add(bitmap);
                        photoPrew.setImageBitmap(bitmap);
                        if (ifConShut) {//连拍
                            if (photoPathList .size() == sheet) {//判断是否拍完
                                //跳转预览裁剪界面
                                go2Crop();
                            }
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        throwable.printStackTrace();
                    }
                });
    }
}
